package cn.edu.ujs.coor.service;

import cn.edu.ujs.coor.common.exception.CoorException;
import cn.edu.ujs.coor.model.*;
import cn.edu.ujs.coor.repository.node.NodeRepository;
import cn.edu.ujs.coor.repository.relation.AccessRepository;
import cn.edu.ujs.coor.repository.relation.GroupUserRelationRepository;
import cn.edu.ujs.coor.repository.relation.ProjectUserRelationRepository;
import cn.edu.ujs.coor.repository.relation.RoleUserRelationRepository;
import cn.edu.ujs.coor.repository.role.RoleRepository;
import cn.edu.ujs.coor.repository.user.UserMapper;
import cn.edu.ujs.coor.repository.user.UserRepository;
import cn.edu.ujs.coor.request.IdRequest;
import cn.edu.ujs.coor.request.auth.LoginRequest;
import cn.edu.ujs.coor.request.auth.RegisterRequest;
import cn.edu.ujs.coor.request.user.ResetPasswordRequest;
import cn.edu.ujs.coor.request.user.UserConfigRequest;
import cn.edu.ujs.coor.request.user.UserUpdateRequest;
import cn.edu.ujs.coor.response.UserResponse;
import cn.edu.ujs.coor.util.BeanUtil;
import cn.edu.ujs.coor.util.JwtUnit;
import cn.edu.ujs.coor.util.SecurityUnit;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 用户相关Service
 *
 * @author 柳曾雄
 * @date 2018-07-16
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class UserService extends BaseService<User, UserResponse> {

    @Autowired
    private AccessRepository accessRepository;

    @Autowired
    private NodeRepository nodeRepository;

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private GroupUserRelationRepository groupUserRelationRepository;

    @Autowired
    private ProjectUserRelationRepository projectUserRelationRepository;

    @Autowired
    private RoleUserRelationRepository roleUserRelationRepository;

    @Autowired
    public void setMapper (UserMapper mapper) {
        this.mapper = mapper;
    }

    @Autowired
    public void setRepository (UserRepository repository) {
        this.repository = repository;
    }

    /**
     * 根据姓名模糊查询
     * @param user
     * @return
     */
    public List<User> findUser (User user) {
        if ("admin".equals(user.getId())) {
            return this.findAll();
        }
        return ((UserRepository) repository).findByOrganizationId(user.getOrganizationId());
    }

    /**
     * 用户注册
     * @param request
     * @return
     */
    public void register (RegisterRequest request) {
        // ID唯一性校验
        if (StringUtils.isNotBlank(request.getId())) {
            User user = findById(request.getId());
            if (user != null) {
                throw new CoorException("er_000002", "用户编号已存在");
            }
        }
        // 联系方式唯一性校验
        if (StringUtils.isNotBlank(request.getPhone())) {
            User user = ((UserRepository) repository).findByPhone(request.getPhone());
            if (user != null) {
                throw new CoorException("er_000002", "该联系方式已存在");
            }
        }
        // 邮箱唯一性校验
        if (StringUtils.isNotBlank(request.getEmail())) {
            User user = ((UserRepository) repository).findByEmail(request.getEmail());
            if (user != null) {
                throw new CoorException("er_000002", "该邮箱已存在");
            }
        }

        // 用户注册
        try {
            User user = (User) request.convertToEntity(User.class);
            user.setPassword(SecurityUnit.MD5(SecurityUnit.MD5(request.getId()) + request.getPassword()));
            save(user);
        } catch (Exception e) {
            e.printStackTrace();
            throw new CoorException("er_000002", "用户注册失败");
        }
    }

    /**
     * 获取用户详情
     * @param request
     * @return
     */
    public UserResponse detail (IdRequest request) {
        User user = this.findById(request.getId());
        if (user == null) {
            throw new CoorException("用户不存在");
        }
        UserResponse response = new UserResponse();
        response.setRoles(roleUserRelationRepository.findByUserId(request.getId()));
        BeanUtil.copyBeanIgnoreNull(response, user);
        return response;
    }

    /**
     * 用户登录
     * @param request
     * @return
     */
    public String login (LoginRequest request) {
        User user = ((UserRepository) repository).findByIdOrPhoneOrEmail(request.getKey());
        // 存在校验
        if (user == null) {
            throw new CoorException("er_000002", "用户不存在");
        }
        // 密码校验
        if (!user.getPassword().equals(SecurityUnit.MD5(SecurityUnit.MD5(user.getId()) + request.getPassword()))) {
            throw new CoorException("er_000002", "用户密码不匹配");
        }

        user.setDataLevel(roleRepository.findMaxLevelByUser(user.getId()));
        return JwtUnit.toJwt(user);
    }

    /**
     * 重置用户密码
     * @param request
     * @return
     */
    public void reset (ResetPasswordRequest request) {
        User user = findById(request.getId());
        if (user == null) {
            throw new CoorException("er_000002", "用户不存在");
        }
        try {
            user.setPassword(SecurityUnit.MD5(SecurityUnit.MD5(request.getId()) + request.getPassword()));
            save(user);
        } catch (Exception e) {
            e.printStackTrace();
            throw new CoorException("er_000002", "重置密码失败");
        }
    }

    /**
     * 更新用户信息
     * @param request
     * @return
     */
    public void update (UserUpdateRequest request) {
        // ID校验
        User user = ((UserRepository) repository).findById(request.getId()).orElse(null);
        if (user == null) {
            throw new CoorException("er_000002", "用户不存在");
        }
        // 联系方式唯一性校验
        if (StringUtils.isNotBlank(request.getPhone()) && !user.getPhone().equals(request.getPhone())) {
            User temp = ((UserRepository) repository).findByPhone(request.getPhone());
            if (temp != null) {
                throw new CoorException("er_000002", "该联系方式已存在");
            }
        }
        // 邮箱唯一性校验
        if (StringUtils.isNotBlank(request.getEmail()) && !user.getEmail().equals(request.getEmail())) {
            User temp = ((UserRepository) repository).findByEmail(request.getEmail());
            if (temp != null) {
                throw new CoorException("er_000002", "该邮箱已存在");
            }
        }

        BeanUtil.copyBeanIgnoreNull(user, request);
        try {
            save(user);
        } catch (Exception e) {
            e.printStackTrace();
            throw new CoorException("er_000002", "更新用户信息失败");
        }

        // 更新角色信息
        roleUserRelationRepository.deleteByUserId(request.getId());
        if (request.getRoles() != null && request.getRoles().size() > 0) {
            for (String roleId : request.getRoles()) {
                RoleUserRelation relation = RoleUserRelation
                        .builder()
                        .roleId(roleId)
                        .userId(request.getId())
                        .build();
                roleUserRelationRepository.save(relation);
            }
        }
    }

    /**
     * 删除用户
     * @param request
     */
    public void delete (IdRequest request) {
        User user = this.findById(request.getId());
        if (user == null) {
            throw new CoorException("er_000002", "该用户不存在");
        }
        // 删除用户关联
        groupUserRelationRepository.deleteByUserId(user.getId());
        projectUserRelationRepository.deleteByUserId(user.getId());
        roleUserRelationRepository.deleteByUserId(user.getId());
        // 删除用户记录
        this.delete(user);
    }

    /**
     * 配置用户信息
     * @param request
     */
    public void config (UserConfigRequest request) {
        User user = this.findById(request.getUserId());
        if (user == null) {
            throw new CoorException("er_000002", "该用户信息不存在");
        }
        // 删除原有关联
        roleUserRelationRepository.deleteByUserId(user.getId());
        // 新建关联
        for (String roleId : request.getRoleIds()) {
            RoleUserRelation relation = RoleUserRelation
                    .builder()
                    .roleId(roleId)
                    .userId(user.getId())
                    .build();
            roleUserRelationRepository.save(relation);
        }
    }

    /**
     * 获取用户信息
     * @return
     */
    public JSONObject info (User user) {
        JSONObject info = (JSONObject) JSON.toJSON(user);
        info.put("access", getAccess(user.getId()));
        return info;
    }

    /**
     * 获取用户访问权限
     * @param userId
     * @return
     */
    private List<Node> getAccess (String userId) {
        if ("admin".equals(userId)) {
            Sort sort = new Sort(Sort.Direction.ASC, "sort");
            return nodeRepository.findAll(sort);
        }
        Set<String> nodeIdSet = new HashSet<>();
        List<String> nodeIdList = new ArrayList<>();
        List<String> roleIds = roleUserRelationRepository.findByUserId(userId);
        for (String roleId : roleIds) {
            nodeIdSet.addAll(accessRepository.findByRoleId(roleId));
        }
        // set去重复
        nodeIdList.addAll(nodeIdSet);
        List<Node> nodes = nodeRepository.findAllById(nodeIdList);
        // 节点根据sort排序
        Collections.sort(nodes, new Comparator<Node>() {
            @Override
            public int compare(Node o1, Node o2) {
                return Integer.parseInt(o1.getSort()) - Integer.parseInt(o2.getSort());
            }
        });
        return nodes;
    }
}